#ifndef __SERVER
#define __SERVER

#include "..\River\River.h"
#include "..\Thread\Thread.h"
#include "..\Client\Client.h"
#include <list>

class Server : public Thread
{
private:
	int m_numthreads;
	River * m_river;
	Client * m_upstream;
	int m_responses;
	char m_message[1024];
	list<pHeader> * m_requested;

	unsigned int m_id;

public:
	Server()
	{
		m_upstream = NULL;
		m_river = new River();
		type(SERVER);
		m_responses = 0;
		m_id = 0;
		m_requested = new list<pHeader>;
	}
	~Server() {}

	list<pHeader> * requested()
	{
		return m_requested;
	}

	list<pHeader> * requested(list<pHeader> * l)
	{
		m_requested = l;
		return requested();
	}
	void add_to_list(packet * p)
	{
		m_requested->push_back(p->Header);
	}
	void upstream(Client * c)
	{
		m_upstream = c;
	}
	int response()
	{
		return m_responses;
	}

	void listen(int port)
	{
		m_river->listen(port);
	}

	void accept(Client * new_client)
	{
		m_river->accept(new_client->river());
	}

	River * river()
	{
		return m_river;
	}

	River * river(River * r)
	{
		m_river = r;
		return river();
	}

	virtual bool process(packet * p)
	{
		LoginPacket * lp;
		switch(p->Header.Type)
		{
		case LOGIN:
			lp = (LoginPacket *)(p->msg);
			switch(p->Header.state)
			{
			case REQUEST:
				sprintf(m_message, "Login request from %d\n", lp->userid);
				m_river->TRACE(5, m_message);

				if(m_river->client_login(lp))
				{
					sprintf(m_message, "Login succeeded for %d\n", lp->userid);
					m_river->TRACE(5, m_message);
					p->Header.state = RESPONSE;
					memcpy(p->msg,lp, sizeof(LoginPacket));
					((Client *)p->Header.object)->push(p);
				}
				else
				{
					if (m_upstream != NULL)
					{
						p->Header.rID = ++m_id;
						pHeader * np = new pHeader();
						*np = p->Header;
						m_requested->push_back(*np);
						p->Header.sID = p->Header.rID;
						m_upstream->push(p);
						sprintf(m_message, "Sent request upstream %d\n", p->Header.rID);
						m_river->TRACE(5, m_message);
					}
					else
					{
						sprintf(m_message, "Login failed for request %d\n", p->Header.sID);
						m_river->TRACE(5, m_message);
						p->Header.state = RESPONSE;
						((Client *)p->Header.object)->push(p); //Login failed
					}
					//go upstream.
				}
				break;
			case RESPONSE:
				m_river->TRACE(5, "Got login response\n");
				if (p->Header.sID > 0)
				{
					m_river->TRACE(5, "Response came from upstream\n");
					for (list<pHeader>::iterator it = m_requested->begin(); it != m_requested->end();	++it)
					{
						if (((pHeader)*it).rID == p->Header.rID)
						{
							m_river->TRACE(5, "Found request on list and sending to client\n");
							p->Header = ((pHeader)*it);
							p->Header.state = RESPONSE;
							((Client *)p->Header.object)->push(p);
							return true;
						}
					}
					sprintf(m_message, "Reponse recieved but not on the list %d\n", p->Header.rID);
					m_river->TRACE(5, m_message);
				}
				else
				{
					m_river->process_login_response(lp);
					m_responses++;
				}
				//delete p;
				break;
			}
			break;
		case EXIT:
			((Client *)p->Header.object)->push(p);
			return false;
		default:
			break;
		}
		return true;
		//delete lp;
	}
};

#endif